home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1992 June: ROMin Holiday / ADC Developer CD (1992-06) (''ROMin Holiday'')_iso / Developer Connection - 06-1992.iso / Developer Essentials / DTS Sample Code / System 7.0 Samples / ProcDoggie 1.0a6 / ProcDoggie.p < prev    next >
Encoding:
Text File  |  1991-02-07  |  17.8 KB  |  583 lines  |  [TEXT/MPS ]

  1. PROGRAM ProcDoggie;
  2.  
  3. {-------------------------------------------------------------------------------
  4. #
  5. #    Apple Macintosh Developer Technical Support
  6. #
  7. #    Main program file for the ProcDoggie application
  8. #
  9. #    Program:    ProcDoggie
  10. #    File:        ProcDoggie.p - Pascal Implementation
  11. #
  12. #    by:        Forrest Tanaka
  13. #
  14. #    Copyright © 1988-1991 Apple Computer, Inc.
  15. #    All rights reserved.
  16. #
  17. --------------------------------------------------------------------------------
  18. #
  19. #    ProcDoggie.p is the root file for ProcDoggie.  It contains the main entry
  20. #    point and the PROGRAM statement, but relies on the other source files
  21. #    included with this application to actually implement the functionality.
  22. #
  23. -------------------------------------------------------------------------------}
  24. {[j=20/57/1$] Pasmat Options}
  25. {$R-}
  26.     
  27.  
  28. (*******************************************************************************
  29. * Used Units
  30. *******************************************************************************)
  31.  
  32.     USES
  33.         (* Group 1 *)
  34.          Types
  35.         ,QuickDraw
  36.  
  37.         (* Group 2 *)
  38.         ,AppleEvents
  39.         ,Controls
  40.         ,DiskInit
  41.         ,Errors
  42.         ,Events
  43.         ,Fonts
  44.         ,Memory
  45.         ,Menus
  46.         ,SegLoad
  47.  
  48.         (* Group 3 *)
  49.         ,Processes
  50.         ,Windows
  51.  
  52.         (* Group 4 *)
  53.         ,Dialogs
  54.  
  55.         (* Application *)
  56.         ,UGlobals
  57.         ,UEmergMem
  58.         ,UProcessUtils
  59.         ,UMenuHandler
  60.         ,UProcessGuts
  61.         ;
  62.  
  63.  
  64. (*******************************************************************************
  65. * Constants
  66. *******************************************************************************)
  67.  
  68.     CONST
  69.         kBecomingActive = TRUE; {Pass to DoActivateEvt; indicates becoming active}
  70.  
  71.  
  72. (*******************************************************************************
  73. * Global Variables
  74. *******************************************************************************)
  75.  
  76.     VAR
  77.         gProcessListWind: WindowPtr; {Pointer to the process list window}
  78.  
  79.  
  80. {$S Main}
  81. (*******************************************************************************
  82. * DoneRequiredParams - Done processing required params; OK?
  83. *
  84. * DoneRequiredParams checks to see if the AppleEvent specified by the
  85. * anAppleEvent parameter has any required parameters that we haven’t yet
  86. * processed.  If there aren’t any left, then noErr is returned.  If there are
  87. * required parameters that haven’t been processed yet, then errAEEventNotHandled
  88. * is returned.  If any other errors occur, then that error code is returned.
  89. *******************************************************************************)
  90.  
  91.     FUNCTION DoneRequiredParams (anAppleEvent: AppleEvent): OSErr;
  92.  
  93.         VAR
  94.             typeCode:   DescType; {Type of AppleEvent attribute found; ignored}
  95.             actualSize: Size;     {Actual size of parameters; ignored}
  96.             error:      OSErr;
  97.  
  98.     BEGIN
  99.         (* Are there any required parameters in AppleEvent we didn’t process? *)
  100.        error := AEGetAttributePtr (anAppleEvent, keyMissedKeywordAttr,
  101.                 typeWildCard, (*<*)typeCode, NIL, 0, (*<*)actualSize);
  102.         IF error = errAEDescNotFound THEN
  103.             (* No required parameters left, so no error *)
  104.             DoneRequiredParams := noErr
  105.         ELSE IF error = noErr THEN
  106.             (* There was at least one required parameter we didn’t process *)
  107.             DoneRequiredParams := errAEEventNotHandled
  108.         ELSE
  109.             (* Some other error happened *)
  110.             DoneRequiredParams := error
  111.     END;
  112.  
  113.  
  114. {$S Main}
  115. (*******************************************************************************
  116. * HandleAEquit - Handler for 'quit' AppleEvent
  117. *
  118. * This is the AppleEvent handler for the 'quit' AppleEvent as passed in the
  119. * quitAppleEvent parameter by the AppleEvent Manager.  The DoQuit routine is
  120. * called which causes this application to quit at the start of the next
  121. * iteration of the main event loop.
  122. *
  123. * Though the quit AppleEvent doesn’t contain any parameters, the standard thing
  124. * to do in reaction to any AppleEvent is to check to see if there are any
  125. * required parameters in the AppleEvent that this routine doesn’t recognise.
  126. * DoneRequiredParms checks for this condition and returns an error if there are
  127. * in fact required parameters in the AppleEvent or if some other error occurs
  128. * during the check.
  129. *******************************************************************************)
  130.  
  131.     FUNCTION HandleAEquit (quitAppleEvent: AppleEvent;
  132.                            reply:          AppleEvent;
  133.                            handlerRefCon:  LongInt): OSErr;
  134.  
  135.         VAR
  136.             error: OSErr;
  137.  
  138.         PROCEDURE RecoverError (errorCode: OSErr);
  139.  
  140.         BEGIN
  141.             HandleAEquit := errorCode;
  142.             EXIT (HandleAEquit)
  143.         END;
  144.  
  145.     BEGIN
  146.         (* quit AE has no parms, but check in case the client requires any *)
  147.         error := DoneRequiredParams (quitAppleEvent);
  148.         IF error <> noErr THEN
  149.             RecoverError (error);
  150.  
  151.         (* Handle the Quit command *)
  152.         DoQuit;
  153.         HandleAEquit := noErr
  154.     END;
  155.  
  156.  
  157. {$S %A5Init}
  158. (*******************************************************************************
  159. * StartUp - Do whatever has to be done to initialize the application
  160. *
  161. * This routine is called after the heap is initialized to initialize the
  162. * application.  This involves initializing the toolbox, emergency memory, and
  163. * loading up the menus.  If any errors occur while doing this, StartUp displays
  164. * an alert telling the user what the error was and then ExitToShell is called.
  165. * This is an unusual way to react to errors, and I only do it here because it’s
  166. * so early in execution that there really isn’t much else that can be done.
  167. *
  168. * See this UEmergMem unit in this application for details about emergency
  169. * memory.
  170. *******************************************************************************)
  171.  
  172.     PROCEDURE StartUp;
  173.  
  174.         CONST
  175.             kSysHandler = TRUE; {Specifies that AE handler is in system heap}
  176.  
  177.         VAR
  178.             error: OSErr;
  179.  
  180.         PROCEDURE HandleError (messageClass: Integer;
  181.                                messageIndex: Integer);
  182.  
  183.             VAR
  184.                 result: Integer; {Result of alert; ignored}
  185.  
  186.         BEGIN
  187.             result := ShowStopAlert (messageClass, messageIndex);
  188.             ExitToShell
  189.         END;
  190.  
  191.     BEGIN
  192.         (* Initialize the toolbox *)
  193.         InitGraf (@thePort);
  194.         InitFonts;
  195.         InitWindows;
  196.         InitMenus;
  197.         TEInit;
  198.         InitDialogs (NIL);
  199.  
  200.         (* Initialize emergency memory *)
  201.         InitEmergMem;
  202.         IF FailLowMemory (0) THEN
  203.             HandleError (rMemErrMessages, kMemErrAppOpenMsg);
  204.  
  205.         (* Load the menus and draw the menu bar *)
  206.         StartMenus;
  207.         IF FailLowMemory (0) THEN
  208.             HandleError (rMemErrMessages, kMemErrAppOpenMsg)
  209.         ELSE IF gError <> noErr THEN
  210.             IF gError = memFullErr THEN
  211.                 HandleError (rMemErrMessages, kMemErrAppOpenMsg)
  212.             ELSE IF gError = resNotFound THEN
  213.                 HandleError (rResErrMessages, kResErrAppDamageMsg)
  214.             ELSE
  215.                 HandleError (rMiscErrMessages, kMiscErrUnknownMsg);
  216.  
  217.         (* Install the AppleEvent handler *)
  218.         error := AEInstallEventHandler (kCoreEventClass, kAEQuitApplication,
  219.                 @HandleAEquit, 0, NOT kSysHandler);
  220.         IF (error = memFullErr) | FailLowMemory (0) THEN
  221.             HandleError (rMemErrMessages, kMemErrAppOpenMsg)
  222.         ELSE IF error <> noErr THEN
  223.             HandleError (rMiscErrMessages, kMiscErrUnknownMsg)
  224.     END;
  225.  
  226.  
  227. {$S Main}
  228. (*******************************************************************************
  229. * Public: DoWindowDrag
  230. *
  231. * A rectangle that covers all screen can be retrieved from the desktop region’s
  232. * rgnBBox.  The desktop region can be retrieved by calling GetGrayRgn.
  233. *******************************************************************************)
  234.  
  235.     PROCEDURE DoWindowDrag (anEvent:       EventRecord;
  236.                             clickedWindow: WindowPtr);
  237.  
  238.         VAR
  239.             dragBounds: Rect; {Window can be dragged over this rectangle}
  240.  
  241.     BEGIN
  242.         (* GetGrayRgn^^.rgnBBox covers the desktop over all screens *)
  243.         dragBounds := GetGrayRgn^^.rgnBBox;
  244.         DragWindow (clickedWindow, anEvent.where, dragBounds)
  245.     END;
  246.  
  247.  
  248. {$S Main}
  249. (*******************************************************************************
  250. * Public: DoContentClick
  251. *
  252. * As new kinds of windows are added to this application, this routine will have
  253. * to be able to detect the new kind of window and dispatch to the routine that
  254. * handles clicks in that kind of window.
  255. *******************************************************************************)
  256.  
  257.     PROCEDURE DoContentClick (anEvent:       EventRecord;
  258.                               clickedWindow: WindowPtr);
  259.  
  260.         VAR
  261.             currWindow: WindowPtr; {Pointer to the current front window}
  262.  
  263.     BEGIN
  264.         currWindow := FrontWindow;
  265.  
  266.         (* Clicked window not in front; activate it *)
  267.         IF currWindow <> clickedWindow THEN
  268.             SelectWindow (clickedWindow)
  269.         ELSE
  270.             IF IsProcessListWindow (clickedWindow) THEN
  271.                 ClickProcessListWindow (clickedWindow, anEvent)
  272.     END;
  273.  
  274.  
  275. {$S Main}
  276. (*******************************************************************************
  277. * Public: DoUpdateEvt
  278. *
  279. * As new kinds of windows are added to this application, this routine will have
  280. * to be able to detect the new kind of window and dispatch to the routine that
  281. * handles update events in that kind of window.
  282. *******************************************************************************)
  283.  
  284.     PROCEDURE DoUpdateEvt (anEvent: EventRecord);
  285.  
  286.         VAR
  287.             eventWindow: WindowPtr; {Pointer to the window to update}
  288.  
  289.     BEGIN
  290.         eventWindow := WindowPtr(anEvent.message);
  291.  
  292.         (* Update the window that needs it *)
  293.         SetPort (eventWindow);
  294.         BeginUpdate (eventWindow);
  295.         IF IsProcessListWindow (eventWindow) THEN
  296.             DrawProcessListWindow (eventWindow)
  297.         ELSE IF IsProcessInfoWindow (eventWindow) THEN
  298.             DrawProcessInfoWindow (eventWindow);
  299.         EndUpdate (eventWindow)
  300.     END;
  301.  
  302.  
  303. {$S Main}
  304. (*******************************************************************************
  305. * Public: DoActivateEvt
  306. *
  307. * As new kinds of windows are added to this application, this routine will have
  308. * to be able to detect the new kind of window and dispatch to the routine that
  309. * handles activate events in that kind of window.
  310. *******************************************************************************)
  311.  
  312.     PROCEDURE DoActivateEvt (eventWind:      WindowPtr;
  313.                              becomingActive: Boolean);
  314.  
  315.     BEGIN
  316.         IF IsProcessListWindow (eventWind) THEN
  317.             ActivateProcessListWindow (eventWind, becomingActive);
  318.     END;
  319.  
  320.  
  321. {$S Main}
  322. (*******************************************************************************
  323. * Public: DoWindowClose
  324. *
  325. * As new kinds of windows are added to this application, this routine will have
  326. * to be able to detect the new kind of window and dispatch to the routine that
  327. * handles close requests for that kind of window.
  328. *******************************************************************************)
  329.  
  330.     PROCEDURE DoWindowClose (anEvent:   EventRecord;
  331.                              eventWind: WindowPtr);
  332.  
  333.     BEGIN
  334.         IF TrackGoAway (eventWind, anEvent.where) THEN
  335.             IF IsProcessInfoWindow (eventWind) THEN
  336.                 CloseProcessInfoWindow (eventWind);
  337.     END;
  338.  
  339.  
  340. {$S Main}
  341. (*******************************************************************************
  342. * DoMouseDown - Mouse-down event dispatcher
  343. *
  344. * When a mouseDown event is received in the main event loop, this routine is
  345. * called to determine which area on the screens the mouseDown was, and to
  346. * dispatch to the appropriate routine to handle mouseDown events in that area.
  347. * The mouseDown event is passed in the anEvent parameter.
  348. *
  349. * See the UMenuHandler unit for routines that handle mouse-down events in the
  350. * menu bar, and the UWindowHandler unit for routines that handle mouse-down
  351. * events in the windows.
  352. *******************************************************************************)
  353.  
  354.     PROCEDURE DoMouseDown (anEvent: EventRecord);
  355.  
  356.         VAR
  357.             clickArea: Integer;   {Area of the screen that was clicked}
  358.             eventWind: WindowPtr; {Pointer the clicked window, if any}
  359.  
  360.     BEGIN
  361.         (* Find clicked area of screen or window *)
  362.         clickArea := FindWindow (anEvent.where, (*<*)eventWind);
  363.  
  364.         (* Jump to mouseDown-handling routine appropriate for screen area *)
  365.         CASE clickArea OF
  366.             inMenuBar:
  367.                 DoMenuChoice (MenuSelect (anEvent.where));
  368.             inContent:
  369.                 DoContentClick (anEvent, eventWind);
  370.             inGoAway:
  371.                 DoWindowClose (anEvent, eventWind);
  372.             inDrag:
  373.                 DoWindowDrag (anEvent, eventWind)
  374.         END
  375.     END;
  376.  
  377.  
  378. {$S Main}
  379. (*******************************************************************************
  380. * DoKeyDown - Key-down event dispatcher
  381. *
  382. * When a keyDown or autoKey event is received in the main event loop, this
  383. * routine is called to determine whether key is a command-key equivalent for a
  384. * menu item or not.  If the command key isn’t down, then the key stroke is
  385. * ignored.  Otherwise, MenuKey is called to get the menu ID and item number
  386. * of the menu item that corresponds to the command key, if any.  Then
  387. * DoMenuChoice is called to dispatch to the appropriate routine for the chosen
  388. * menu item.  The keyDown or autoKey event is passed in anEvent.
  389. *
  390. * See the UMenuHandler unit for routines that handle menu events.
  391. *******************************************************************************)
  392.  
  393.     PROCEDURE DoKeyDown (anEvent: EventRecord);
  394.  
  395.         VAR
  396.             theKey: Char; {ASCII code of key that was pressed}
  397.  
  398.     BEGIN
  399.         (* Get the ASCII code of the pressed key *)
  400.         theKey := CHR (BAND (anEvent.message, charCodeMask));
  401.  
  402.         (* If anEvent was keyDown and command key was down, it’s menu command *)
  403.         IF (anEvent.what = keyDown) AND (BAND (anEvent.modifiers, cmdKey) <> 0)
  404.                 THEN
  405.             DoMenuChoice (MenuKey (theKey))
  406.     END;
  407.  
  408.  
  409. {$S Main}
  410. (*******************************************************************************
  411. * DoDiskEvt - Handle a disk-insert event
  412. *
  413. * This routine is called whenever this application receives an event indicating
  414. * that a disk was inserted.  If the disk can’t be mounted, the message field of
  415. * the event reflects the error, and we call DIBadMount to allow the user to
  416. * format the disk.
  417. *******************************************************************************)
  418.  
  419.     PROCEDURE DoDiskEvt (anEvent: EventRecord);
  420.  
  421.         CONST
  422.             kSysAlertLeft = 80; {Left coord of DIBadMount alert in screen coords}
  423.             kSysAlertTop  = 80; {Top coord of DIBadMount alert in screen coords}
  424.  
  425.         VAR
  426.             cornerPoint: Point; {Top-left corner of DIBadMount alert}
  427.             error:       OSErr;
  428.  
  429.     BEGIN
  430.         IF HiWrd (anEvent.message) <> noErr THEN
  431.             BEGIN
  432.                 SetPt ((*<*)cornerPoint, kSysAlertLeft, kSysAlertTop);
  433.                 error := DIBadMount (cornerPoint, anEvent.message)
  434.             END
  435.     END;
  436.  
  437.  
  438. {$S Main}
  439. (*******************************************************************************
  440. * Public: DoOSEvt
  441. *
  442. * When an OS Event is received, it can be a suspend or resume event.
  443. *******************************************************************************)
  444.  
  445.     PROCEDURE DoOSEvt (anEvent: EventRecord);
  446.  
  447.         VAR
  448.             eventWindow: WindowPtr; {Pointer to window being activated/deactivated}
  449.             osEvtKind:   Byte;      {Kind of OSEvt; mouse-moved or suspend/resume}
  450.  
  451.     BEGIN
  452.         (* Only care if anEvent is suspend/resume event *)
  453.         osEvtKind := BAND (BSR (anEvent.message, 24), $00FF);
  454.         IF osEvtKind = suspendResumeMessage THEN
  455.             BEGIN
  456.                 (* It’s a suspend/resume event; suspend or resume? *)
  457.                 eventWindow := FrontWindow;
  458.                 IF BAND (anEvent.message, 1) <> 0 THEN
  459.                     BEGIN
  460.                         (* Resume event; set the cursor and activate front window *)
  461.                         InitCursor;
  462.                         IF eventWindow <> NIL THEN
  463.                             DoActivateEvt (eventWindow, kBecomingActive);
  464.                         gWereInFront := TRUE
  465.                     END
  466.                 ELSE
  467.                     BEGIN
  468.                         (* Suspend event; deactivate the front window *)
  469.                         IF eventWindow <> NIL THEN
  470.                             DoActivateEvt (eventWindow, NOT kBecomingActive);
  471.                         gWereInFront := FALSE
  472.                     END
  473.             END
  474.     END;
  475.  
  476.  
  477. {$S Main}
  478. (*******************************************************************************
  479. * DoHighLevelEvent - Handle a high-level event
  480. *
  481. * This routine handles the high-level event specified by anEvent.  The only
  482. * high-level events that this application handles are AppleEvents, so I just
  483. * pass the high-level event to AEProcessAppleEvent.  AEProcessAppleEvent calls
  484. * the appropriate AppleEvent handler routine to handle that particular kind of
  485. * AppleEvent.
  486. *******************************************************************************)
  487.  
  488.     PROCEDURE DoHighLevelEvent (anEvent: EventRecord);
  489.  
  490.         VAR
  491.             error: OSErr;
  492.  
  493.     BEGIN
  494.         error := AEProcessAppleEvent (anEvent);
  495.     END;
  496.  
  497.  
  498. {$S Main}
  499. (*******************************************************************************
  500. * EventLoop - Main event loop for this application
  501. *
  502. * This is the main event loop of this application.  During every iteration of
  503. * the event loop, the menus are kept up-to-date, and the Process List window and
  504. * all of the open Process Information windows are given time to update
  505. * themselves to current conditions.  Also, NoEmergMem is called to detect
  506. * whether the emergency memory was used.  If it was, then RecoverEmergMem is
  507. * called in an attept to get it back.  If it can’t, then some commands could be
  508. * disabled until the memory can be recovered.
  509. *******************************************************************************)
  510.  
  511.     PROCEDURE EventLoop;
  512.  
  513.         VAR
  514.             anEvent: EventRecord; {An incoming event}
  515.  
  516.     BEGIN
  517.         FixMenus;
  518.         InitCursor;
  519.         gWereInFront := WereInFront;
  520.         gQuitting := FALSE;
  521.  
  522.         (* We loop “forever,” or until the Quit handler calls ExitToShell *)
  523.         WHILE NOT gQuitting DO
  524.             BEGIN
  525.                 (* Give all open windows some time *)
  526.                 IdleAllProcessWindows;
  527.  
  528.                 (* Try to reallocate emergency memory if it’s been used *)
  529.                 IF NoEmergMem THEN
  530.                     RecoverEmergMem;
  531.  
  532.                 (* Fix the menus to reflect current conditions *)
  533.                 FixMenus;
  534.  
  535.                 (* It’s time to get and examine an event *)
  536.                 IF WaitNextEvent (everyEvent, (*<*)anEvent, kMaxSleepTime, NIL) THEN
  537.                     BEGIN
  538.                         CASE anEvent.what OF
  539.                             mouseDown:
  540.                                 DoMouseDown (anEvent);
  541.                             keyDown, autoKey:
  542.                                 DoKeyDown (anEvent);
  543.                             updateEvt:
  544.                                 DoUpdateEvt (anEvent);
  545.                             diskEvt:
  546.                                 DoDiskEvt (anEvent);
  547.                             activateEvt:
  548.                                 DoActivateEvt (WindowPtr(anEvent.message),
  549.                                         BAND (anEvent.modifiers, activeFlag) <> 0);
  550.                             osEvt:
  551.                                 DoOSEvt (anEvent);
  552.                             kHighLevelEvent:
  553.                                 DoHighLevelEvent (anEvent)
  554.                         END
  555.                     END
  556.             END
  557.     END;
  558.  
  559.  
  560. BEGIN
  561.     (* Set up the heap *)
  562.     MaxApplZone;
  563.     MoreMasters;
  564.     MoreMasters;
  565.     MoreMasters;
  566.     MoreMasters;
  567.     MoreMasters;
  568.     MoreMasters;
  569.  
  570.     (* Do anything that must be done at program start-up *)
  571.     StartUp;
  572.     UnloadSeg (@StartUp);
  573.  
  574.     (* Set the default launch mode *)
  575.     SetLaunchMode (kJustLaunch);
  576.  
  577.     (* Open the process list window *)
  578.     gProcessListWind := CreateProcessListWindow;
  579.  
  580.     (* Enter the main event loop *)
  581.     EventLoop
  582. END.
  583.